#ifndef __tenacitas_state_machine_processor__transitions__h__
#define __tenacitas_state_machine_processor__transitions__h__



/** @file */


/** @todo */

// ==> C++ Headers
#include <map>

// ==> 3rds Headers

// ==> Our Headers
#include "transition.h"

// ==> Namespaces
using namespace std;

// ==> Macro Constants

// ==> Macro Commands


/** ==> namespace of the organization */
namespace tenacitas {
    /** ==> namespace for the project */
    namespace state_machine {
        /**  ==> exhibitor, integrator, processor, storer, communicator */
        namespace processor {

            // ==> Typedefs 

            // ==> Pre-Declarations

            // ==> Attributes 

            // ==> Functions

            // ==> Classes

            /** 
                @nosubgrouping 
            */
            template<typename t_supplier>
            class transitions {

                // ==> transitions - Friends

                /** Class allowed to access private members of @p transitions, in ordey
                    to perform tests */
                friend class transitions_tester;

            public:

                // ==> transitions - Public Internal Types

                /** Must implement 
                    @code

                    @endcode
                */
                typedef t_supplier supplier;

                /** Must implement 
                    @code

                    @endcode
                */
                typedef typename supplier::event event;

                /** Must implement 
                    @code

                    @endcode
                */                
                typedef typename supplier::state state;

                /** Must implement 
                    @code

                    @endcode
                */
                typedef typename supplier::handler handler;

                /** */
                typedef transition<supplier> transition;

                // ==> transitions - Public Constructors


                /** Destructor */
                ~transitions( );

                /** */
                transitions(state && p_initial, state && p_final)
                    : m_map() {
                    m_initial = std::move(p_initial);
                    m_final = std::move(p_final);
                    m_current = m_initial;
                }

                // ==> transitions - Public Accessors

                /** */
                const state & current() const {
                    return m_current;
                }
                

                // ==> transitions - Public Helpers

                // ==> transitions - Public Processors

                /** */
                template <typename ...t_args>
                bool change(state && p_final, t_args... p_params) {
                    bool l_rc = true;
                    
                    map::iterator l_ite = m_map.find(m_current);
                    while(true) {
                        if (l_ite != m_map.end()) {
                            break;
                        }
                        if (l_ite->value().first == p_final) {
                            l_ite->value().second(p_params);
                            break;
                        }
                    }
                    if (l_ite == m_map.end()) {
                        l_rc = false;
                    }
                    return l_rc;
                }
                


                // ==> transitions - Public Operators

                // ==> transitions - Public Attributes

            private:

                // ==> transitions - Private Internal Types
                std::multimap<state, std::pair<state, handler>> map;

                // ==> transitions - Private Constructors

                // ==> transitions - Private Accessors

                // ==> transitions - Private Helpers

                // ==> transitions - Private Processors

                // ==> transitions - Private Operators

                // ==> transitions - Private Attributes

                map m_map;

                /** */
                state m_initial;

                /** */
                state m_final;

                /** */
                state m_current;
            };
        }
    }
}
// =============================================================================
// I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::state_machine::processor;


#endif
